package com.kgc.itrip.controller;

import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.DefaultAlipayClient;
import com.alipay.api.domain.AlipayTradeWapPayModel;
import com.alipay.api.internal.util.AlipaySignature;
import com.alipay.api.request.AlipayTradePagePayRequest;
import com.kgc.itrip.common.Constants;
import com.kgc.itrip.common.EmptyUtils;
import com.kgc.itrip.component.ValidationToken;
import com.kgc.itrip.config.AlipayConfig;
import com.kgc.itrip.pojo.ItripHotelOrder;
import com.kgc.itrip.service.LocalService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Map;

/**
 * 支付宝支付的控制器
 *
 * @author lrg on 2021/4/1
 * @since 1.0.0
 */
@Api(value = "支付宝支付的控制器")
@Controller
@RequestMapping("/api")
public class AlipayController {
    @Resource
    private AlipayConfig alipayConfig;
    @Resource
    private ValidationToken validationToken;
    @Resource
    private LocalService localService;
    @ApiOperation(value = "支付之前获取订单信息，让用户确认",
            httpMethod = "POST",notes = "根据用户名、密码进行统一认证"+
            "100305：订单ID不能为空"+
            "100305：token失效"+
            "300003:系统异常",
            protocols = "http",produces = "application/json;charset=UTF-8",
            consumes = "application/json")
    @RequestMapping(value = "/prepay/{orderNo}/",method = RequestMethod.GET)
    public String perPay(@PathVariable String orderNo, Model model, HttpServletRequest request){
        try{
            /*//返回的map集合中的key值是flag,和前端已经约定好了的
            //要验证用户登录先要获取token，user-agent
            //1.获取token
            String token = request.getHeader("token");
            //2.获取user-agent
            String agent = request.getHeader("User-Agent");
            //3.验证用户是否登录
            boolean validate = validationToken.validate(agent,token);
            if (!validate){//说明没有登录
                return "redirect:"+alipayConfig.getLoginUrl();
            }*/
            ItripHotelOrder itripHotelOrderByOrder = localService.getItripHotelOrderByOrderNo(orderNo);
            if(EmptyUtils.isEmpty(itripHotelOrderByOrder)){
                return "notfound";
            }
            model.addAttribute("order",itripHotelOrderByOrder.getOrderNo());
            model.addAttribute("hotelName",itripHotelOrderByOrder.getHotelName());
            model.addAttribute("payAmount",itripHotelOrderByOrder.getPayAmount());
            model.addAttribute("roomId",itripHotelOrderByOrder.getRoomId());
            model.addAttribute("count",itripHotelOrderByOrder.getCount());
            return "pay";
        }catch (Exception e){
            e.printStackTrace();
            return "error";
        }
    }

    @RequestMapping(value="/pay",method= RequestMethod.POST)
    public void orderPay(String WIDout_trade_no,String WIDtotal_amount,
                         String WIDsubject,String WIDbody, HttpServletResponse response) throws AlipayApiException, IOException {
        String product_code = "FAST_INSTANT_TRADE_PAY";
        //获得初始化的AlipayClient
        AlipayClient alipayClient =
                new DefaultAlipayClient(alipayConfig.getGatewayUrl(),
                        alipayConfig.getApp_id(),
                        alipayConfig.getPrivatekey(),
                        "json",
                        alipayConfig.getCharset(),
                        alipayConfig.getAlipayPublicKey(),
                        alipayConfig.getSignType());

        //设置请求参数
        AlipayTradePagePayRequest alipayRequest = new AlipayTradePagePayRequest();
        alipayRequest.setReturnUrl(alipayConfig.getReturnUrl());
        alipayRequest.setNotifyUrl(alipayConfig.getNotifyUrl());
        // 封装请求支付信息
        AlipayTradeWapPayModel model = new AlipayTradeWapPayModel();
        model.setOutTradeNo(WIDout_trade_no);
        model.setTotalAmount(WIDtotal_amount);
        model.setSubject(WIDsubject);
        //model.setTimeExpire(timeout_express);
        model.setProductCode(product_code);//必须设置这个属性，产品编码
        alipayRequest.setBizModel(model);
        //请求
        String result = alipayClient.pageExecute(alipayRequest).getBody();
        response.setContentType("text/html;charset=UTF-8");
        PrintWriter out = response.getWriter();
        //输出
        out.println(result);
        out.flush();
        out.close();
    }
    /**
     * 支付宝的同步通知的处理方法
     * 同步通知处理之后主要是通知用户支付结果
     * @return
     */
    @RequestMapping(value="/returnurl",method = RequestMethod.GET)
    public String aliPayReturn(HttpServletRequest request) throws Exception {
        //更具请求获取支付宝回掉
        Map<String,String> params = localService.getAliPayCallbackParams(request);
        //验证签名，如果返回true表示验证签名成功
        boolean signVerified = AlipaySignature.rsaCheckV1(params,
                alipayConfig.getAlipayPublicKey(),
                alipayConfig.getCharset(),
                alipayConfig.getSignType()); //调用SDK验证签名
        //商户订单号
        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
        //支付宝交易号
        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
        //付款金额
        String total_amount = new String(request.getParameter("total_amount").getBytes("ISO-8859-1"),"UTF-8");
        //获取订单对象
        ItripHotelOrder itripHotelOrderByOrder = localService.getItripHotelOrderByOrderNo(out_trade_no);
        if(!signVerified) {
            //获取支付失败后的地址
            String failureUrl = alipayConfig.getFailureUrl();
            String format = String.format(failureUrl,itripHotelOrderByOrder.getOrderNo(),itripHotelOrderByOrder.getId().toString());
            return "redirect:"+format;
        }
        //如果代码走到这里说明支付成功
        //调用业务逻辑层去执行订单操作和插入数据和添加交易记录
        localService.itriptxUpafateItripHotelOrder(out_trade_no,trade_no, Constants.PAYTYPE.AIL_PAY);
        //获取成功支付后的跳转地址
        String successUrl = alipayConfig.getSuccessUrl();
        String format = alipayConfig.getFailureUrl();
        return "redirect:"+format;
    }


    /**
     * 异步通知支付宝会在25小时之内向我们的程序发起8次请求
     * 支付宝的异步通知的处理方法
     * 异步通知不需要通知用户，只需要通知支付宝
     */
    @RequestMapping(value = "/notifyurl",method = RequestMethod.POST)
    public void aliPayNotify(HttpServletRequest request,HttpServletResponse response) throws Exception {
        //获取支付宝POST过来反馈信息
        Map<String,String> params = localService.getAliPayCallbackParams(request);
        boolean signVerified = AlipaySignature.rsaCheckV1(params,
                alipayConfig.getAlipayPublicKey(),
                alipayConfig.getCharset(),
                alipayConfig.getSignType()); //调用SDK验证签名
        /* 实际验证过程建议商户务必添加以下校验：
        1、需要验证该通知数据中的out_trade_no是否为商户系统中创建的订单号，
        2、判断total_amount是否确实为该订单的实际金额（即商户订单创建时的金额），
        3、校验通知中的seller_id（或者seller_email) 是否为out_trade_no这笔单据的对应的操作方（有的时候，一个商户可能有多个seller_id/seller_email）
        4、验证app_id是否为该商户本身。
        */
        PrintWriter out = response.getWriter();
        if(!signVerified) {//验证失败
            out.println("fail");
            out.flush();
            out.close();
            return ;
            //调试用，写文本函数记录程序运行情况是否正常
            //String sWord = AlipaySignature.getSignCheckContentV1(params);
            //AlipayConfig.logResult(sWord);
        }
        //如果代码能走到这里说明验证签名成功
        //商户订单号
        String out_trade_no = new String(request.getParameter("out_trade_no").getBytes("ISO-8859-1"),"UTF-8");
        //支付宝交易号
        String trade_no = new String(request.getParameter("trade_no").getBytes("ISO-8859-1"),"UTF-8");
        //调用业务逻辑层去执行订单操作和插入数据和添加交易记录
        localService.itriptxUpafateItripHotelOrder(out_trade_no,trade_no, Constants.PAYTYPE.AIL_PAY);
        out.println("success");
        out.flush();
        out.close();
    }
}
